/*
 * Copyright (c) 2011-2012 Tygron Serious Gaming
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'Swing to Nifty Converter' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package nl.tygron.niftyconverter.converters;

import java.awt.Component;
import java.awt.Container;
import java.lang.reflect.Field;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.SwingConstants;
import nl.tygron.niftyconverter.ImageDatabase;
import nl.tygron.niftyconverter.UIConverterDatabase;
import nl.tygron.niftyconverter.elements.NElement;
import nl.tygron.niftyconverter.elements.NiftyStructure;
import nl.tygron.niftyconverter.util.NiftyUtils;

/**
 * @author Jeroen Warmerdam, Raymond Weijermars
 * @Specialism GUI
 * @Maintainer Jeroen Warmerdam
 */
public abstract class ComponentConverter {

	private static final Logger logger = Logger.getLogger(ComponentConverter.class.getName());

	protected int x = 0;
	protected int y = 0;
	protected int width = 0;
	protected int height = 0;
	protected String id = "";

	protected ImageDatabase dbase;
	protected boolean onlyCheckContainer = false;

	public ComponentConverter(ImageDatabase newDbase) {

		this.dbase = newDbase;
	}

	/**
	 * @param component
	 */
	public NElement convert(Component component, NiftyStructure nStructure, UIConverterDatabase uiConverterDatabaseRef,
	        Component topMostObject) {

		return decorateNiftyComponent(component, nStructure, uiConverterDatabaseRef, topMostObject);
	}

	/**
	 * @param component
	 * @param niftyComponent
	 */
	private NElement decorateNiftyComponent(Component component, NiftyStructure nStructure, UIConverterDatabase uiConverterDatabaseRef,
	        Component topMostObject) {

		this.x = component.getX();
		this.y = component.getY();
		this.width = component.getWidth();
		this.height = component.getHeight();
		this.id = this.getObjectFieldName(component, topMostObject);
		String componentName = topMostObject.getClass().getSimpleName();
		componentName = NiftyUtils.deCapitalizeFirstLetter(componentName);

		if (this.id.contains("Undefined")) { // undefined jpanels happen at the start of our panels. we just want the panel name in this
			// case.
			this.id = componentName;
		} else { // for uniqueness we make sure subpanels/elements of a panel carry the panel name. thismakes sure that you don't get
			// generic names like button1 etc..
			// Set the first letter of id to Uppercase
			this.id = NiftyUtils.capitalizeFirstLetter(this.id);
			this.id = componentName + "_" + this.id;// we add the name of the panel or screen for clarification and uniqueness.
		}
		return detailedDecorateNiftyComponent(component, nStructure, uiConverterDatabaseRef, topMostObject);
	}

	protected abstract NElement detailedDecorateNiftyComponent(Component comp, NiftyStructure nStructure,
	        UIConverterDatabase uiConverterDatabaseRef, Component topMostObject);

	protected String getImageIconLocation(ImageIcon imageIcon) {

		String iconDescription = imageIcon.getDescription();
		iconDescription = iconDescription.substring(6);

		try {
			String binNeedle = "bin/";
			String imageLocation = iconDescription.substring(iconDescription.indexOf(binNeedle) + binNeedle.length());
			imageLocation = imageLocation.replace("\\", "/");
			imageLocation = dbase.findCorrectCase(imageLocation);
			return imageLocation;
		} catch (Exception e) {

			e.printStackTrace();
		}

		return null;

	}

	protected String getObjectAlignment(int alignmentValue) {

		String value = "wrongAlignment";

		switch (alignmentValue) {
			case SwingConstants.BOTTOM:
				value = "bottom";
				break;
			case SwingConstants.CENTER:
				value = "center";
				break;
			case SwingConstants.LEFT:
				value = "left";
				break;
			case SwingConstants.RIGHT:
				value = "right";
				break;
			case SwingConstants.TOP:
				value = "top";
				break;
			default:
				value = "left";
				break;
		}
		return value;
	}

	protected String getObjectFieldName(Object fieldObject, Object parent) {

		if (fieldObject == null || parent == null) {

			logger.severe("Error converting object to fieldname, because object or parent is null: [" + fieldObject + ", " + parent + "]");
			return null;
		}

		try {

			Field[] fields = parent.getClass().getDeclaredFields();
			for (Field field : fields) {

				field.setAccessible(true);
				Object value = field.get(parent);

				if (value != null && value.equals(fieldObject)) {
					String fieldName = field.getName();
					logger.info("Return name of " + fieldObject.getClass().getSimpleName() + ": " + fieldName);
					return fieldName;
				}
			}
		} catch (IllegalAccessException e) {

			logger.severe(e.toString());
		}

		return "Undefined_" + fieldObject.getClass().getSimpleName();
	}

	public boolean isOnlyCheckContainer() {

		return onlyCheckContainer;
	}

	public void onlyCheckContainer(NElement parent, Component comp, NiftyStructure nStructure, UIConverterDatabase uiConverterDatabaseRef,
	        Component topMostObject) {

		logger.severe("This method has not been implemented for this Converter and therefore should not be called.");
	}

	protected void recurseThroughChildren(NElement nElement, Component component, NiftyStructure nStructure,
	        UIConverterDatabase uiConverterDatabaseRef, Component topMostObject) {

		Component[] comps = ((Container) component).getComponents();
		for (int i = comps.length - 1; i > -1; i--) {
			uiConverterDatabaseRef.retrieveComponents(comps[i], nElement, nStructure, topMostObject);
		}
	}
}
